package designpattern;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 代理模式实现
 * 1. 简介
 * 一个类代表另一个类的功能
 * 主要解决
 * 直接访问对象时带来的问题
 * 何时使用
 * 想在访问一个类时做一些控制
 * 2. 优点
 * (1) 职责清晰
 * (2) 高拓展
 * (3) 智能化
 * 3. 缺点
 * (1) 创建对象的过程变慢
 * (2) 实现非常复杂
 * 4. 注意
 * (1) 和适配器的区别: 适配器模式改变所考虑的接口，代理模式不修改代理类的接口
 * (2) 和装饰器模式的区别: 装饰器为了增强功能，代理为了控制
 * 5. 实现步骤
 * //1. 创建一个接口
 * //2. 创建一个真实的对象
 * //3. 创建JDK代理类
 */
public class ProxyTest {
    public static void main(String[] args) {
        // 真实对象
        RealImage realImage = new RealImage("mingc ");
//        realImage.setName("名称");
        // (1)创建代理对象
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realImage);
        Image image = (Image) Proxy.newProxyInstance(realImage.getClass().getClassLoader(),
                realImage.getClass().getInterfaces(),
                myInvocationHandler);
        image.display();
    }
}

// 1. 创建接口
interface Image {
    void display();
}

// 2. 创建实现类（真实对象）
class RealImage implements Image {
    String name;

    public RealImage(String name) {
        this.name = name;
    }

    @Override
    public void display() {
        System.out.println("display....." + name);
    }
}


// 3. 创建代理类
// (1) 使用JDK自带的代理类InvocationHandler
class MyInvocationHandler implements InvocationHandler {
    Image image;

    public MyInvocationHandler(Image image) {
        this.image = image;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用代理类");
        if (method.getName().equals("display")) {
            Object invoke = method.invoke(image, args);
            System.out.println("调用display方法:invoke值:" + invoke);
            return invoke;
        } else {
            return "";
        }
    }
}